2

Promise

本文从js的异步处理出发,引入Promise的概念,并且介绍Promise对象以及其API方法。

js里的异步处理

可以参考这篇文章
js是单线程的,
在js里,异步处理总共有四种方法,其中最常见的一种方法是采用回调函数的方式

function f1(callback){
    setTimeout(function(){
        callback();
    },1000)
}

f1(f2);

另外除了回调函数,事件监听的机制也会进行异步处理。任务的执行不取决于代码的顺序,而是取决于事件是否会发生。

如果是业务逻辑不复杂还好说,可是如果业务逻辑很复杂的话,回调嵌套的很多,代码书写起来会变得很复杂很难看懂。
还有一个问题是,如果有多个异步操作,那么就存在一个处理顺序的问题,代码如何按照希望的顺序执行。

Promise

简介

Promise是抽象异步处理对象以及对其进行各种操作的组件。Promise并不是从js里出现的概念。
Promise则是把类似的异步处理对象和处理规则进行规范化, 并按照采用统一的接口来编写,而采取规定方法之外的写法都会出错。

首先说,Promise是一个对象,所以说这个对象与js里的其他对象没什么不一样的。要说与众不同的地方时,Promise对象充当代理的作用,充当异步操作和回调函数之间的中介

Promise的思想是:每次执行一个异步操作以后,立刻返回一个Promise对象,因为是立刻操作,所以我们可以进行同步操作流程。这个Promise对象有一个then方法,指定回调函数,用于在异步操作执行完后执行回调函数处理。

//换成Promise的写法
new Promise(f5).then(f4).then(f3).then(f2).then(f1)

使用Promise,用同步的写法处理异步操作的代码,使得代码清晰易懂,等一个异步函数处理完成之后,才会执行下一个then里边的函数。这样就避免了前边的多个回调可能引发的顺序问题。

Promise接口

前边说过,Promise接口的作用是,返回一个Promise对象。
一个Promise对象有三种状态

  • pending 异步操作未完成

  • resolve 异步操作已成功完成

  • reject 异步操作失败

至于这三种关系的途径可以描述为两种

pending ---> resolve
pending ---> reject

这种变化只会出现一次。所以,意思是,一个异步操作结束之后只会有两种状态,成功or失败。异步操作成功时,Promise对象返回一个值,对象状态变为resolve,异步操作失败时,对象状态变为reject。

Promise对象用then方法添加回调函数,then方法支持链式调用。

promise.then(onFulfilled, onRejected)

then方法接受两个参数,看名字就知道第一个参数是Promise对象状态时resolve的时候调用,而第二个参数可以省略,表示Promise调用失败状态是reject的时候执行这个回调。

除了then方法,还有一个专门处理异常的方法.
.catch 也可以理解为 promise.then(undefined, onRejected) 。

promise.catch(onRejected)

then和catch两个方法是写到了Promise对象的原型上的,每个Promise对象都可以调用。

Promise对象的生成

ES6提供了原生的Promise对象构造函数,用于生成Promise对象,

var promise = new Promise(function(resolve, reject){
  // 异步操作的代码

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

Promise对象接收一个函数作为构造函数的参数,这个函数同样有两个参数,这两个参数是由js引擎提供的函数,不用自己来部署。
resolve函数的作用是把Promise对象的状态从pending变为resolve,在异步操作成功的时候调用,并且将异步操作的结果作为参数传过去。同样的,reject函数的作用是把对象状态从pending变成reject,在失败的时候调用,并且传递结果参数。

接下来,当Promise对象创建成功之后就可以用then方法链式调用了。

Promise对象其他方法
1.Promise.resolve()

一般情况下,我们会用构造函数的方法创建Promise对象。但是,除此之外我们也会有其他方法创建。
静态方法Promise.resolve(value)被认为是new Promise方式创建Promise对象的快捷方式。

Promise.resolve(42).then(function(value){
    console.log(value);
})

resolve()会让对象状态立即变成resolved,并且将形参立刻传给下一个回调。

2.Promise.reject()

这个方法类似上一个方法,也是创建Promise对象的快捷方式,但是只会把Promise对象从pending变为rejected。参数是一个异常对象,传递给下一个catch方法或者then方法。

Promise.reject(new Error("BOOM!")).catch(function(error){
    console.error(error);
});
3.Promise.all() && Promise.race()

到目前为止,已经学习了创建Promise对象和用then,catch方法来注册回调函数。如果只有一个Promise对象的话很好说,但是如果有多个Promise对象的时候要如何处理呢。

Promise.all 接收一个 promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态的时候,它才会去调用 .then 方法。

Promise.race 只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理。

4. 每次调用then都会返回一个新创建的promise对象
function f1(v){
    console.log(v);
    return 2;
}
function f2(v){
    console.log(v)
}
Promise.resolve(1).then(f1).then(f2);

张小草1018
285 声望8 粉丝